#region Terms of Usage
/*
 * Copyright 2006 Sameera Perera
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
#endregion

using System;
using System.Collections.Generic;
using System.Text;
using needle.Services.soab.Data;
using needle.Services.soab.Cache;

namespace needle.Services.soab.RequestQueue
{
    /// <summary>Status of a <see cref="ServiceRequest"/></summary>
    public enum ServiceRequestStatus
    {
        /// <summary>The request has not yet beeen queued.</summary>
        Dirty,
        /// <summary>The request has been queued.</summary>
        Queued,
        /// <summary>The request has been transfered but not yet acknowledged.</summary>
        Transfered,
        /// <summary>The request has been completed.</summary>
        Completed,
        /// <summary>An exception occured during transfer.</summary>
        Errored
    }

    /// <summary>
    /// Represents a request sent to the webservice.
    /// </summary>
    public class ServiceRequest
    {
        private object payload;
        /// <summary>Gets or sets the payload delivered as the service request</summary>
        public object Payload
        {
            get { return payload; }
            set { payload = value; }
        }

        private ServiceRequestStatus status = ServiceRequestStatus.Dirty;
        /// <summary>Gets or sets the current status of the request.</summary>
        public ServiceRequestStatus Status
        {
            get { return status; }
            set { status = value; }
        }
        
        private string remoteMethodName;
        /// <summary>The name of the method to be invoked in the Service proxy.</summary>
        public string RemoteMethodName
        {
            get { return remoteMethodName; }
            set { remoteMethodName = value; }
        }
        
        private ServiceContext svcContext;
        /// <summary>Gets or sets the ServiceContext which to operate on.</summary>
        public ServiceContext ServiceContext
        {
            get { return svcContext; }
            set { svcContext = value; }
        }
                
        private string callbackMethodName;
        /// <summary>
        /// Gets or sets a list of service requests that should only be invoked
        /// once the current request has successfully executed.
        /// </summary>
        public string CallbackMethodName
        {
            get { return callbackMethodName; }
            set { callbackMethodName = value; }
        }

        /// <summary>Gets whether the ServiceRequest can be executed.</summary>
        /// <remarks>A request can only be executed once all its dependencies have been
        /// resolved.</remarks>
        public bool CanExecute
        {
            get
            {
                if ( this.payload is ICacheDependant )
                {
                    ICacheDependant icd = (ICacheDependant)this.payload;
                    Database.Instance.RefreshObject( this.payload, icd.ResolutionDepth );
                    return icd.IsResolved;
                }
                else
                    return true;
            }
        }

        public ServiceRequest()
        {
        }

        #region System.Object Method Overrides

        public override bool Equals( object obj )
        {
            // A service request must have the RemoteMethodName and CallbackMethodName specified
            // for it to be complete. Incomplete objects are not equal to anything else.
            if ( this.remoteMethodName != null 
                    && this.callbackMethodName != null
                    && obj is ServiceRequest )
            {
                // ServiceRequests are equal when they match in RemoteMethodName, 
                // CallbackMethodName and Payload value.
                ServiceRequest rqst = (ServiceRequest)obj;
                bool retVal = ( this.payload == null && rqst.Payload == null ) 
                                || ( this.payload != null && this.payload.Equals( rqst.Payload ) );
                retVal      = retVal 
                                && this.callbackMethodName.Equals( rqst.CallbackMethodName )
                                && this.remoteMethodName.Equals( rqst.RemoteMethodName );
                return retVal;
            }
            else
                return false;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        #endregion
    }
}
